/*
 * Copyright (c) 2017 Trail of Bits, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

TEST_BEGIN_64(PCMPISTRIv128v128i8_eq_any, 1)
TEST_INPUTS(0)

    // "aeiouy"
    mov eax, 0
    push rax
    movabs rax, 0x000079756f696561
    push rax
    movdqu xmm0, [rsp]

    // "You Drive Me M"
    movabs rax, 0x00004d20654d2065
    push rax
    movabs rax, 0x7669724420756f59
    push rax
    movdqu xmm1, [rsp]

    pcmpistri xmm0,xmm1,0x0
TEST_END_64


TEST_BEGIN_64(PCMPISTRIv128v128i8_eq_ranges, 1)
TEST_INPUTS(0)

    // "azAZ"
    mov eax, 0
    push rax
    movabs rax, 0x5a417a61
    push rax
    movdqu xmm0, [rsp]

    // "You Drive Me M"
    movabs rax, 0x00004d20654d2065
    push rax
    movabs rax, 0x7669724420756f59
    push rax
    movdqu xmm1, [rsp]

    pcmpistri xmm0,xmm1,0x4
TEST_END_64

// Performs a single string compare between two XMM regs. The comparison
// result is spread across ECX and the arithmetic flags, so we combine those
// into a single number, then push that onto the stack so that we can compare
// the native and lifted stacks to see the result of every comparison.
#define C(a, b, i) \
    pcmpistri xmm ## a, xmm ## b, i ; \
    mov eax, ecx ; \
    bswap eax ; \
    bswap rax ; \
    lahf ; \
    push rax ;

#define MAKE_TEST(name, i) \
    TEST_BEGIN_64(name, 1) ; \
    TEST_INPUTS(0) ; \
        mov eax, 0 ; \
        C(0, 0, i) C(0, 1, i) C(0, 2, i) C(0, 3, i) C(0, 4, i) C(0, 5, i) C(0, 6, i) C(0, 7, i) \
        C(1, 0, i) C(1, 1, i) C(1, 2, i) C(1, 3, i) C(1, 4, i) C(1, 5, i) C(1, 6, i) C(1, 7, i) \
        C(2, 0, i) C(2, 1, i) C(2, 2, i) C(2, 3, i) C(2, 4, i) C(2, 5, i) C(2, 6, i) C(2, 7, i) \
        C(3, 0, i) C(3, 1, i) C(3, 2, i) C(3, 3, i) C(3, 4, i) C(3, 5, i) C(3, 6, i) C(3, 7, i) \
        C(4, 0, i) C(4, 1, i) C(4, 2, i) C(4, 3, i) C(4, 4, i) C(4, 5, i) C(4, 6, i) C(4, 7, i) \
        C(5, 0, i) C(5, 1, i) C(5, 2, i) C(5, 3, i) C(5, 4, i) C(5, 5, i) C(5, 6, i) C(5, 7, i) \
        C(6, 0, i) C(6, 1, i) C(6, 2, i) C(6, 3, i) C(6, 4, i) C(6, 5, i) C(6, 6, i) C(6, 7, i) \
        C(7, 0, i) C(7, 1, i) C(7, 2, i) C(7, 3, i) C(7, 4, i) C(7, 5, i) C(7, 6, i) C(7, 7, i) \
    TEST_END_64

MAKE_TEST(PCMPISTRIv128v128i8_0, 0)
MAKE_TEST(PCMPISTRIv128v128i8_1, 1)
MAKE_TEST(PCMPISTRIv128v128i8_2, 2)
MAKE_TEST(PCMPISTRIv128v128i8_3, 3)
MAKE_TEST(PCMPISTRIv128v128i8_4, 4)
MAKE_TEST(PCMPISTRIv128v128i8_5, 5)
MAKE_TEST(PCMPISTRIv128v128i8_6, 6)
MAKE_TEST(PCMPISTRIv128v128i8_7, 7)
MAKE_TEST(PCMPISTRIv128v128i8_8, 8)
MAKE_TEST(PCMPISTRIv128v128i8_9, 9)
MAKE_TEST(PCMPISTRIv128v128i8_10, 10)
MAKE_TEST(PCMPISTRIv128v128i8_11, 11)
MAKE_TEST(PCMPISTRIv128v128i8_12, 12)
MAKE_TEST(PCMPISTRIv128v128i8_13, 13)
MAKE_TEST(PCMPISTRIv128v128i8_14, 14)
MAKE_TEST(PCMPISTRIv128v128i8_15, 15)
MAKE_TEST(PCMPISTRIv128v128i8_16, 16)
MAKE_TEST(PCMPISTRIv128v128i8_17, 17)
MAKE_TEST(PCMPISTRIv128v128i8_18, 18)
MAKE_TEST(PCMPISTRIv128v128i8_19, 19)
MAKE_TEST(PCMPISTRIv128v128i8_20, 20)
MAKE_TEST(PCMPISTRIv128v128i8_21, 21)
MAKE_TEST(PCMPISTRIv128v128i8_22, 22)
MAKE_TEST(PCMPISTRIv128v128i8_23, 23)
MAKE_TEST(PCMPISTRIv128v128i8_24, 24)
MAKE_TEST(PCMPISTRIv128v128i8_25, 25)
MAKE_TEST(PCMPISTRIv128v128i8_26, 26)
MAKE_TEST(PCMPISTRIv128v128i8_27, 27)
MAKE_TEST(PCMPISTRIv128v128i8_28, 28)
MAKE_TEST(PCMPISTRIv128v128i8_29, 29)
MAKE_TEST(PCMPISTRIv128v128i8_30, 30)
MAKE_TEST(PCMPISTRIv128v128i8_31, 31)
MAKE_TEST(PCMPISTRIv128v128i8_32, 32)
MAKE_TEST(PCMPISTRIv128v128i8_33, 33)
MAKE_TEST(PCMPISTRIv128v128i8_34, 34)
MAKE_TEST(PCMPISTRIv128v128i8_35, 35)
MAKE_TEST(PCMPISTRIv128v128i8_36, 36)
MAKE_TEST(PCMPISTRIv128v128i8_37, 37)
MAKE_TEST(PCMPISTRIv128v128i8_38, 38)
MAKE_TEST(PCMPISTRIv128v128i8_39, 39)
MAKE_TEST(PCMPISTRIv128v128i8_40, 40)
MAKE_TEST(PCMPISTRIv128v128i8_41, 41)
MAKE_TEST(PCMPISTRIv128v128i8_42, 42)
MAKE_TEST(PCMPISTRIv128v128i8_43, 43)
MAKE_TEST(PCMPISTRIv128v128i8_44, 44)
MAKE_TEST(PCMPISTRIv128v128i8_45, 45)
MAKE_TEST(PCMPISTRIv128v128i8_46, 46)
MAKE_TEST(PCMPISTRIv128v128i8_47, 47)
MAKE_TEST(PCMPISTRIv128v128i8_48, 48)
MAKE_TEST(PCMPISTRIv128v128i8_49, 49)
MAKE_TEST(PCMPISTRIv128v128i8_50, 50)
MAKE_TEST(PCMPISTRIv128v128i8_51, 51)
MAKE_TEST(PCMPISTRIv128v128i8_52, 52)
MAKE_TEST(PCMPISTRIv128v128i8_53, 53)
MAKE_TEST(PCMPISTRIv128v128i8_54, 54)
MAKE_TEST(PCMPISTRIv128v128i8_55, 55)
MAKE_TEST(PCMPISTRIv128v128i8_56, 56)
MAKE_TEST(PCMPISTRIv128v128i8_57, 57)
MAKE_TEST(PCMPISTRIv128v128i8_58, 58)
MAKE_TEST(PCMPISTRIv128v128i8_59, 59)
MAKE_TEST(PCMPISTRIv128v128i8_60, 60)
MAKE_TEST(PCMPISTRIv128v128i8_61, 61)
MAKE_TEST(PCMPISTRIv128v128i8_62, 62)
MAKE_TEST(PCMPISTRIv128v128i8_63, 63)
MAKE_TEST(PCMPISTRIv128v128i8_64, 64)
MAKE_TEST(PCMPISTRIv128v128i8_65, 65)

MAKE_TEST(PCMPISTRIv128v128i8_66, 66)
MAKE_TEST(PCMPISTRIv128v128i8_67, 67)
MAKE_TEST(PCMPISTRIv128v128i8_68, 68)
MAKE_TEST(PCMPISTRIv128v128i8_69, 69)
MAKE_TEST(PCMPISTRIv128v128i8_70, 70)
MAKE_TEST(PCMPISTRIv128v128i8_71, 71)
MAKE_TEST(PCMPISTRIv128v128i8_72, 72)
MAKE_TEST(PCMPISTRIv128v128i8_73, 73)
MAKE_TEST(PCMPISTRIv128v128i8_74, 74)
MAKE_TEST(PCMPISTRIv128v128i8_75, 75)
MAKE_TEST(PCMPISTRIv128v128i8_76, 76)
MAKE_TEST(PCMPISTRIv128v128i8_77, 77)
MAKE_TEST(PCMPISTRIv128v128i8_78, 78)
MAKE_TEST(PCMPISTRIv128v128i8_79, 79)
MAKE_TEST(PCMPISTRIv128v128i8_80, 80)

MAKE_TEST(PCMPISTRIv128v128i8_81, 81)
MAKE_TEST(PCMPISTRIv128v128i8_82, 82)
MAKE_TEST(PCMPISTRIv128v128i8_83, 83)
MAKE_TEST(PCMPISTRIv128v128i8_84, 84)
MAKE_TEST(PCMPISTRIv128v128i8_85, 85)
MAKE_TEST(PCMPISTRIv128v128i8_86, 86)
MAKE_TEST(PCMPISTRIv128v128i8_87, 87)
MAKE_TEST(PCMPISTRIv128v128i8_88, 88)
MAKE_TEST(PCMPISTRIv128v128i8_89, 89)
MAKE_TEST(PCMPISTRIv128v128i8_90, 90)
MAKE_TEST(PCMPISTRIv128v128i8_91, 91)
MAKE_TEST(PCMPISTRIv128v128i8_92, 92)
MAKE_TEST(PCMPISTRIv128v128i8_93, 93)

MAKE_TEST(PCMPISTRIv128v128i8_94, 94)
MAKE_TEST(PCMPISTRIv128v128i8_95, 95)
MAKE_TEST(PCMPISTRIv128v128i8_96, 96)
MAKE_TEST(PCMPISTRIv128v128i8_97, 97)
MAKE_TEST(PCMPISTRIv128v128i8_98, 98)
MAKE_TEST(PCMPISTRIv128v128i8_99, 99)
MAKE_TEST(PCMPISTRIv128v128i8_100, 100)
MAKE_TEST(PCMPISTRIv128v128i8_101, 101)
MAKE_TEST(PCMPISTRIv128v128i8_102, 102)
MAKE_TEST(PCMPISTRIv128v128i8_103, 103)
MAKE_TEST(PCMPISTRIv128v128i8_104, 104)
MAKE_TEST(PCMPISTRIv128v128i8_105, 105)
MAKE_TEST(PCMPISTRIv128v128i8_106, 106)
MAKE_TEST(PCMPISTRIv128v128i8_107, 107)
MAKE_TEST(PCMPISTRIv128v128i8_108, 108)
MAKE_TEST(PCMPISTRIv128v128i8_109, 109)
MAKE_TEST(PCMPISTRIv128v128i8_110, 110)
MAKE_TEST(PCMPISTRIv128v128i8_111, 111)
MAKE_TEST(PCMPISTRIv128v128i8_112, 112)

MAKE_TEST(PCMPISTRIv128v128i8_113, 113)
MAKE_TEST(PCMPISTRIv128v128i8_114, 114)
MAKE_TEST(PCMPISTRIv128v128i8_115, 115)
MAKE_TEST(PCMPISTRIv128v128i8_116, 116)
MAKE_TEST(PCMPISTRIv128v128i8_117, 117)
MAKE_TEST(PCMPISTRIv128v128i8_118, 118)
MAKE_TEST(PCMPISTRIv128v128i8_119, 119)
MAKE_TEST(PCMPISTRIv128v128i8_120, 120)
MAKE_TEST(PCMPISTRIv128v128i8_121, 121)
MAKE_TEST(PCMPISTRIv128v128i8_122, 122)
MAKE_TEST(PCMPISTRIv128v128i8_123, 123)
MAKE_TEST(PCMPISTRIv128v128i8_124, 124)
MAKE_TEST(PCMPISTRIv128v128i8_125, 125)
MAKE_TEST(PCMPISTRIv128v128i8_126, 126)
MAKE_TEST(PCMPISTRIv128v128i8_127, 127)

#undef C
#undef MAKE_TEST
